#include <iostream>
using namespace std;
// class Person
//{
// public:
//	void Print()
//	{
//		cout << "_name" << _name << endl;
//		cout << "_age" << _age << endl;
//	}
// protected:
//	string _name = "peter";
//	int _age = 18;
// };
//
// class Student :public Person
//{
// protected:
//	int _stuid;
// };
// class Teacher :public Person
//{
//	int _jobid;
// };
//
// int main()
//{
//	Student t;
//	Person p = t;  //切片：子类对象可以赋值给父类（基类）的对象
//
//	char ch = 'a';
//	int i = 97;
//	if (ch == i)
//	{
//		cout << "相等" << endl;
//	}
//	else
//	{
//		cout << "不相等" << endl;
//	}
//
//
//
//	return 0;
// }

// 1.上面特殊处理，两个类型转换的时候不会产生临时变量
//	不像是double d=i; const double& r=i;这个会产生临时变量

// class Person
//{
// public:
//	//构造函数
//	Person(const char* name = "peter")
//		: _name(name)
//	{
//		cout << "Person()" << endl;
//	}
//	//拷贝构造
//	Person(const Person& p)
//		: _name(p._name)
//	{
//		cout << "Person(const Person& p)" << endl;
//	}
//	//赋值重载
//	Person& operator=(const Person & p)
//	{
//		cout << "Person operator=(const Person& p)" << endl;
//		if (this != &p)
//			_name = p._name;
//		return *this;
//	}
//	//析构函数
//	~Person()
//	{
//		cout << "~Person()" << endl;
//	}
// protected:
//	string _name; // 姓名
// };
//
// class Student : public Person
//{
// public:
//	//构造函数
//	Student(const char* name, int num)
//		: Person(name)//name是父类的，调用父类的构造函数
//		, _num(num)
//	{
//		cout << "Student()" << endl;
//	}
//	//拷贝构造
//	Student(const Student& s)
//		: Person(s)
//		, _num(s._num)
//	{
//		cout << "Student(const Student& s)" << endl;
//	}
//	//赋值重载
//	Student& operator = (const Student& s)
//	{
//		cout << "Student& operator= (const Student& s)" << endl;
//		if (this != &s)
//		{
//			Person::operator =(s);
//			_num = s._num;
//		}
//		return *this;
//	}
//
//
//	//子类的析构函数和父类的析构函数构成隐藏函数，所以调不到
//	//由于后面多态的原因，析构函数被特殊处理，名字会统一处理成destructor
//
//
//	//为了保证先子后父，父类的析构会在子类的析构后自动调用
//
//	~Student()
//	{
//		//不这样写Person::~Person();
//		cout << "~Student()" << endl;
//	}
//
// protected:
//	int _num; //学号
// };
////void Test()
////{
////	Student s1;
////	//Student s1("jack", 18);
////	//Student s2(s1);
////	//Student s3("rose", 17);
////	//s1 = s3;
////
////}
// int main()
//{
//	//默认生成构造函数：
//	//派生类的成员：1.内置类型和自定义类型分别处理
//	//基类的成员：调用父类的构造函数
//
//	//总结：派生这些默认成员函数规则，其实跟以前类似，
//	//唯一不同的是：不管是构造初始化/拷贝/析构，多了父类那一部分，原则：父类那部分调用父类的对应函数
//
//	Student s1("张三", 1);
//
//	Student s2(s1);
//
//	Student s3("李四", 54);
//
//	//s1 = s3;
//
//
//	return 0;
// }

// class Person
//{
// public:
//     // 析构函数
//     ~Person()
//     {
//         cout << "~Person()" << endl; // 输出析构信息
//     }
//
// protected:
//     string _name; // 姓名
// };
//
// class Student : public Person
//{
// public:
//     // 子类的析构函数
//     ~Student()
//     {
//         //Person::~Person();  不可以这样写
//         cout << "~Student()" << endl; // 输出析构信息
//     }
//
// protected:
//     int _num; // 学号
// };
//
// int main()
//{
//     Student* s = new Student(); // 创建 Student 对象
//     delete s; // 删除对象，将调用析构函数
//     return 0;
// }

// 继承与友元
// class Student; // 前向声明
//
// class Person {
// public:
//     friend void Display(const Person& p, const Student& s); // 声明友元函数
//
// protected:
//     string _name; // 姓名
// };
//
// class Student : public Person {
// public:
//    // friend void Display(const Person& p, const Student& s);
// protected:
//     int _stuNum; // 学号
// };
//
//// 友元函数实现
// void Display(const Person& p, const Student& s) {
//     cout << "Name: " << p._name << endl; // 可以访问 Person 的 _name
//     cout << "Student Number: " << s._stuNum << endl; // 可以访问 Student 的 _stuNum
// }
//
// int main()
//{
//     Person p;
//     Student s;
//     Display(p, s);
// }

// #include <iostream>
// using namespace std;
//
// class Base {
// private:
//     int baseData;
//
// public:
//     Base(int data) : baseData(data) {}
//
//     // 基类友元函数
//     friend void displayBase(Base& b);
// };
//
//// 友元函数的定义
// void displayBase(Base& b) {
//     cout << "Base data: " << b.baseData << endl; // 访问基类的私有成员
// }
//
// class Derived : public Base {
// private:
//     int derivedData;
//
// public:
//     Derived(int baseData, int derivedData) : Base(baseData), derivedData(derivedData) {}
//
//     // 基类的友元函数不能访问派生类的私有成员
//     friend void displayDerived(Derived& d);
// };
//
//// 友元函数的定义
// void displayDerived(Derived& d) {
//     // 友元函数 displayBase 无法访问 derivedData
//     // cout << "Derived data: " << d.derivedData << endl; // 编译错误
//
//     // 友元函数 displayBase 只能访问 Base 的私有成员
//     displayBase(d); // 仍然可以调用基类的友元函数
// }
//
// int main() {
//     Base b(10);
//     displayBase(b); // 访问基类的私有成员
//
//     Derived d(20, 30);
//     displayDerived(d); // 访问派生类的私有成员
//     return 0;
// }

// 写博客
// ————————————————————————————————————————————————————————————————————————————————————————————

// 1.概念
//  继承后父类的Person的成员（成员函数+成员变量）都会变成子类的一部分。这里体现出了
// Student和Teacher复用了Person的成员。下面我们使用监视窗口查看Student和Teacher对象，可
// 以看到变量的复用。调用Print可以看到成员函数的复用。

// class Person
//{
// public:
//	void Print()
//	{
//		cout << "name:" << _name << endl;
//		cout << "age:" << _age << endl;
//	}
// protected:
//	string _name = "peter"; // 姓名
//	int _age = 18; // 年龄
// };
// class Student : public Person
//{
// protected:
//	int _stuid; // 学号
// };
//
// class Teacher : public Person
//{
// protected:
//	int _jobid; // 工号
// };
// int main()
//{
//	Student s;
//	Teacher t;
//	s.Print();
//	t.Print();
//	return 0;
// }

// class Person
//{
// public:
//	void Print()
//	{
//		cout << "age:" << _age << endl;
//	}
// protected:
//	int _age = 18; // 年龄
// };
// class Student : public Person
//{
// protected:
//	int _stuid; // 学号
// };
//
// class Teacher : public Person
//{
// protected:
//	int _jobid; // 工号
// };
// int main()
//{
//	Student s;
//
//	//_age是protected成员，不能在类外（如main函数中）直接访问。
//	//cout << s._age << endl;
//
//	//Print() 是 Person 类的public成员函数，能被派生类Student对象直接调用。
//	//在Print()函数内部，_age成员是可访问的，因为它是 Person 的protected成员，允许Person内部的函数访问。
//	s.Print();//但能间接访问
//	return 0;
// }

// class Person {
// protected:
//     string _name;  // 姓名
//     string _sex;   // 性别
//     int _age;      // 年龄
// };
//
// class Student : public Person {
// public:
//     int _No;  // 学号
// };

// void Test() {
//     Student sobj;
//     sobj._No = 100;  // 设置学号
//
//     // 1. 子类对象可以赋值给父类对象（对象切割）
//     Person pobj = sobj;  // 这里会发生对象切割，Student的_No将会丢失
//     // pobj中只保留了Person类的成员，_No没有保留
//
//     // 1. 子类对象可以赋值给父类指针
//     Person* pp = &sobj;  // 这样是安全的，指针指向的是完整的Student对象，但通过pp只能访问Person的成员
//
//     // 1. 子类对象可以赋值给父类引用
//     Person& rp = sobj;  // rp引用sobj的Person部分
// }

// void Test() {
//     Student sobj;
//     Person* pp = &sobj;  // pp指向派生类对象
//
//     // 3. 基类指针可以通过强制类型转换赋值给派生类指针
//     Student* ps1 = (Student*)pp;  // 这种转换是安全的，因为pp指向的是Student对象
//     ps1->_No = 10;  // 访问派生类的成员是安全的
//
//     Person pobj;
//     pp = &pobj;  // pp现在指向的是基类对象
//
//     // 3. 强制类型转换的隐患
//     Student* ps2 = (Student*)pp;  // 虽然可以转换，但不安全
//     // ps2->_No = 10;  // 未定义行为！pp实际上指向的是Person对象，访问派生类成员会越界
// }
// int main()
//{
//     Test();
//     return 0;
// }

//// 基类 Person
// class Person {
// protected:
//     string _name; // 姓名
//     string _sex;  // 性别
//     int _age;     // 年龄
//
// public:
//     Person(string name, string sex, int age)
//         : _name(name), _sex(sex), _age(age) {}
//
//     // 打印基本信息
//     void printInfo() const {
//         cout << "Name: " << _name << ", Sex: " << _sex << ", Age: " << _age << endl;
//     }
// };
//
//// 派生类 Student，继承自 Person
// class Student : public Person {
// public:
//     int _No; // 学号
//
//     // 构造函数
//     Student(string name, string sex, int age, int No)
//         : Person(name, sex, age)
//         , _No(No)
//     {}
//
//     // 打印学生信息
//     void printStudentInfo() const {
//         printInfo(); // 调用基类方法
//         cout << "Student No: " << _No << endl;
//     }
// };
//
//// 测试函数
// void Test() {
//     // 创建一个派生类对象
//     Student sobj("Alice", "Female", 20, 12345);
//
//     // 1. 派生类对象赋值给基类对象（会发生切片）
//     Person pobj = sobj; // 只复制了Person部分
//     pobj.printInfo(); // 输出基类信息，派生类特有部分丢失
//
//     // 2. 基类对象不能赋值给派生类对象
//     // sobj = pobj; // 错误，无法将基类对象赋值给派生类对象
//
//     // 3. 基类指针指向派生类对象
//     Person* pp = &sobj; // 基类指针指向派生类对象
//     pp->printInfo(); // 调用基类方法，输出基类信息
//
//     // 4. 强制类型转换
//     Student* ps1 = (Student*)pp; // 安全，因为pp指向sobj
//     ps1->_No = 10; // 修改派生类的成员
//     ps1->printStudentInfo(); // 输出完整信息
//
//     // 5. 基类指针指向基类对象
//     pp = &pobj; // pp现在指向基类对象
//     // Student* ps2 = (Student*)pp; // 不安全，pp指向基类对象
//     // ps2->_No = 10; // 错误，未定义行为
//
// }
//
// int main() {
//     Test(); // 调用测试函数
//     return 0;
// }

// class Person
//{
// protected:
//	string _name = "小李子";
//	int _num = 4203899;//身份证号
// };
//
// class Student :public Person
//{
// public:
//	void Print()
//	{
//		cout << " 姓名:" << _name << endl;
//		cout << " 身份证号:" << Person::_num << endl; //要用 基类::基类成员
//		//cout << " 身份证号:" <<_num << endl;   //这样就打印的是学号而不是基类中的身份证号
//		cout << " 学号:" << _num << endl;
//	}
// protected:
//	int _num = 001;//学号
// };
// int main()
//{
//	Student s1;
//	s1.Print();
//	return 0;
// }

// B中的fun和A中的fun不是构成重载，因为不是在同一作用域
// B中的fun和A中的fun构成隐藏，成员函数满足函数名相同就构成隐藏。
// class A
//{
// public:
//	void fun()
//	{
//		cout << "func()" << endl;
//	}
//};
// class B : public A
//{
// public:
//	void fun(int i)
//	{
//		A::fun();
//		cout << "func(int i)->" << i << endl;
//	}
//};
// int main()
//{
//	B b;
//	b.fun(10);
//	return 0;
//};

//
// class human {
// public:
//	string name = "小明";
//	void print()
//	{
//		cout << name << endl;
//	}
//};
// class student :public human {
// public:
//	string name = "小红";
//	void print(int x)
//	{
//		cout << name << endl;
//	}
//};
// int main()
//{
//	student st;
//	st.print();
//	return 0;
//}

// 继承与静态成员
// class Person
//{
// public:
//	Person() { ++_count; }
// protected:
//	string _name; // 姓名
// public:
//	static int _count; // 统计人的个数。
// };
//
// int Person::_count = 0;
//
// class Student : public Person
//{
// protected:
//	int _stuNum; // 学号
// };
//
// class Graduate : public Student
//{
// protected:
//	string _seminarCourse; // 研究科目
// };
//
// void TestPerson()
//{
//	Student s1;
//	Student s2;
//	Student s3;
//	Graduate s4;
//	cout << " 人数 :" << Person::_count << endl;
//	Student::_count = 0;
//	cout << " 人数 :" << Person::_count << endl;
// }
// int main()
//{
//	TestPerson();
//	return 0;
// }

// 菱形继承。二义性
// class Person
//{
// public:
//	string _name; // 姓名
// };
// class Student : public Person
////class Student :virtual public Person
//{
// protected:
//	int _num; //学号
//};
// class Teacher : public Person
////class Teacher :virtual  public Person
//{
// protected:
//	int _id; // 职工编号
//};
// class Assistant : public Student, public Teacher
//{
// protected:
//	string _majorCourse; // 主修课程
//};
// void Test()
//{
//	// 这样会有二义性无法明确知道访问的是哪一个
//	Assistant a;
//	a._name = "peter";
//	// 需要显示指定访问哪个父类的成员可以解决二义性问题，但是数据冗余问题无法解决
//	a.Student::_name = "xxx";
//	a.Teacher::_name = "yyy";
//}

////...
// class Student :virtual public Person
//{
// protected:
//	int _num; //学号
// };
// class Teacher :virtual  public Person
//{
// protected:
//	int _id; // 职工编号
// };
// void Test()
//{
//	Assistant a;
//	a._name = "peter";
// }
////.....

// class A
//{
// public:
//	int _a;
// };
//  //class B : public A
// class B : virtual public A
//{
// public:
//	int _b;
// };
////class C : public A
// class C : virtual public A
//{
// public:
//	int _c;
// };
// class D : public B, public C
//{
// public:
//	int _d;
// };
// int main()
//{
//	D d;
//	d.B::_a = 1;
//	d.C::_a = 2;
//	d._b = 3;
//	d._c = 4;
//	d._d = 5;
//	return 0;
// }

class A
{
public:
    virtual void func(int val = 1) { std::cout << "A->" << val << std::endl; }
    virtual void test() { func(); }
};
class B : public A
{
public:
    void func(int val = 0) { std::cout << "B->" << val << std::endl; }
};
int main(int argc, char *argv[])
{
    B *p = new B;
    p->test();
    return 0;
}